<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 定长参数
      function add1(a, b, c, d) {
        // arguments是当前函数的聚合参数
        return [...arguments].reduce((a, b) => a + b);
      }
      // 一个函数需要的参数个数可以通过fn.length 获得 验证请看后面验证1
      function currying1(fn) {
        let len = fn.length;
        let args = [];
        return function _c(...newArgs) {
          // 合并参数
          args = [...args, ...newArgs];
          // 判断当前参数集合args的长度是否 < 目标函数fn的需求参数长度
          if (args.length < len) {
            // 继续返回函数
            return _c;
          } else {
            // 返回执行结果
            return fn.apply(this, args.slice(0, len));
          }
        };
      }
      let addCurry = currying1(add1);
      let total = addCurry(1)(2)(3)(4); // 同时支持addCurry(1)(2, 3)(4)该方式调用
      console.log(total); // 10

      // 验证1
      function name(params, params2, params3) {}
      function name2(fn) {
        console.log(fn.length);
      }
      name2(name);

      // =========================================非定长参数==================================
      function add2(...args) {
        return args.reduce((a, b) => a + b);
      }

      function currying2(fn) {
        let args = [];
        return function _c(...newArgs) {
          if (newArgs.length) {
            args = [...args, ...newArgs];
            return _c;
          } else {
            return fn.apply(this, args);
          }
        };
      }

      let addCurry2 = currying2(add2);
      // 注意调用方式的变化
      console.log(addCurry2(1)(2)(3)(4, 5)());
    </script>
  </body>
</html>
